#include <sys/epoll.h>
#include <unistd.h>
#include "Log.hpp"
#include "Common.hpp"

using namespace myLog;

const static int default_epfd = -1;

class Epoller{
private:
    void EpollCtlHelper(int op, int fd, uint32_t events){
        epoll_event ev;
        ev.events = events;
        ev.data.fd = fd; //这个是有用的！ -> 到时候用于查询对应的_connections来进行操作！
        int n = epoll_ctl(_epfd, op, fd, &ev);
        if(n < 0) LOG(LogLevel::WARNING) << "epoll ctl error!";
        else LOG(LogLevel::INFO) << "epoll ctl success! fd is " << fd;
    }

public:
    Epoller()
        :_epfd(default_epfd)
    {
        int n = _epfd = epoll_create(256);
        if(n < 0){
            LOG(LogLevel::FATAL) << "epoll create error!!!";
            exit(EPOLL_CREATE_ERROR);
        }
        else LOG(LogLevel::INFO) << "epoll create success, epfd is " << _epfd;
    }

    ~Epoller(){
        int close_id = close(_epfd);
        if(close_id == 0) LOG(LogLevel::INFO) << "the epoll fd is closed" << _epfd;
    }


    //添加事件
    void AddEvent(int fd, uint32_t events){
        EpollCtlHelper(EPOLL_CTL_ADD, fd, events);
    }

    //删除事件
    void DelEvent(int fd){
        int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
        (void)n;
    }

    //修改事件
    void ModEvent(int fd, uint32_t events){
        EpollCtlHelper(EPOLL_CTL_MOD, fd, events);
    }   

    //等待事件就绪
    int WaitEvent(epoll_event evs[], int max_evs, int timeout){
        int n = epoll_wait(_epfd, evs, max_evs, timeout);
        if(n < 0) LOG(LogLevel::WARNING) << "epoll_wait error!!!";
        else if(n == 0) LOG(LogLevel::WARNING) << "epoll_wait timeout...";
        else LOG(LogLevel::WARNING) << "epoll_wait success!!!";
        return n;
    }
    
private:
    int _epfd;
};